﻿// TODO:

//decrypt:
//- when we decrypt we try every recipientInfo as long as we find a privateKey. Usually this privateKey
//   is found on the Smartcard which is inserted in the Smartcard-Reader-Device.
//   We have an own interface to the smartcard and an own Datev CSP. 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Security.Cryptography.X509Certificates;
using System.IO;

namespace LargeCMS
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            // For SignedLargeCMS test
            subjectSignTextBox.Text = "NOMBRE";
            subjectCosignTextBox.Text = "ALEJANDRO";
            dataSignTextBox.Text = "Test1KB.txt";
            dataCosignTextBox.Text = "Test1KB.txt";
            dataVerifyTextBox.Text = "Test1KB.txt";
            encodedSignTextBox.Text = "encodeddata.p7s";
            encodedCosignTextBox.Text = "encodeddata.p7s";
            decodedCosignTextBox.Text = "decodeddata.txt";
            reencodedCosignTextBox.Text = "reencodeddata.p7s";
            encodedVerifyTextBox.Text = "";
            decodedVerifyTextBox.Text = "decodeddata.txt";

            // For EnvelopedLargeCMS test
            subject1EncodeTextBox.Text = "NOMBRE";
            subject2EncodeTextBox.Text = "ALEJANDRO";
            dataEncodeTextBox.Text = "Test1KB.txt";
            encodedEncodeTextBox.Text = "encodeddata.p7s";
            encodedDecodeTextBox.Text = "encodeddata.p7s";
            decodedDecodeTextBox.Text = "decodeddata.txt";
        }

        #region "SignedLargeCMS Test"

        private void signButton_Click(object sender, EventArgs e)
        {
            // Variables
            X509Store store = null;
            X509Certificate2 cert = null;
            FileStream dataFile = null;
            FileStream encodedFile = null;
            SignedLargeCMS cms = null;

            try
            {
                // Get signer cert
                store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
                store.Open(OpenFlags.MaxAllowed);
                cert = store.Certificates.Find(X509FindType.FindBySubjectName, subjectSignTextBox.Text, true)[0];

                // Open file with data to encode
                dataFile = File.Open(dataSignTextBox.Text, FileMode.Open);

                // Create file for encoded message
                encodedFile = File.Create(encodedSignTextBox.Text);

                // Sign data
                cms = new SignedLargeCMS();
                cms.EncodeAndSign(cert, detachedSignCheckBox.Checked, dataFile, encodedFile);

                // Success. Inform user
                MessageBox.Show("Signature computed successfully!!!\nNote: if message is detached, verify signature in detached mode");
                detachedVerifyCheckBox.Checked = detachedSignCheckBox.Checked;
                dataVerifyTextBox.Text = dataSignTextBox.Text;
                encodedVerifyTextBox.Text = encodedSignTextBox.Text;
            }
            catch (Exception ex)
            {
                // Show errors
                if (ex.InnerException != null)
                {
                    MessageBox.Show(ex.Message + "\n" + ex.InnerException.Message);
                }
                else
                {
                    MessageBox.Show(ex.Message);
                }
            }
            finally
            {
                // Clean up
                if (store != null) { store.Close(); }
                if (dataFile != null) { dataFile.Close(); }
                if (encodedFile != null) { encodedFile.Close(); }
                if (cms != null) { cms.Dispose(); }                
            }
        }

        private void cosignButton_Click(object sender, EventArgs e)
        {
            // Variables
            X509Store store = null;
            X509Certificate2 cert = null;
            FileStream dataFile = null;
            FileStream encodedFile = null;
            FileStream decodedFile = null;
            FileStream reencodedFile = null;
            SignedLargeCMS cms = null;

            try
            {
                // Get cosigner cert
                store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
                store.Open(OpenFlags.MaxAllowed);
                cert = store.Certificates.Find(X509FindType.FindBySubjectName, subjectCosignTextBox.Text, true)[0];

                // Open file with encoded message
                encodedFile = File.Open(encodedCosignTextBox.Text, FileMode.Open);

                // Create file for re-encoded data
                reencodedFile = File.Create(reencodedCosignTextBox.Text);


                // Original message is detached
                if (detachedCosignCheckBox.Checked)
                {
                    // Open file with original data
                    dataFile = File.Open(dataCosignTextBox.Text, FileMode.Open);

                    // Cosign message. Note that when using streaming, the reencoded file is always detached
                    cms = new SignedLargeCMS();
                    cms.CoSign(cert, dataFile, encodedFile, null, reencodedFile);
                }

                // Original message is not detached
                else
                {
                    // Open file with original data
                    decodedFile = File.Create(decodedCosignTextBox.Text);

                    // Cosign message. Note that when using streaming, the reencoded file is always detached
                    cms = new SignedLargeCMS();
                    cms.CoSign(cert, null, encodedFile, decodedFile, reencodedFile);
                }

                // Success. Inform user
                MessageBox.Show("Signature computed successfully!!!\nNote: co-signed message is always detached when using streaming, so verify signature in detached mode");
                detachedVerifyCheckBox.Checked = true;
                encodedVerifyTextBox.Text = reencodedCosignTextBox.Text;
                if (detachedCosignCheckBox.Checked)
                {
                    dataVerifyTextBox.Text = dataCosignTextBox.Text;
                }
                else
                {
                    dataVerifyTextBox.Text = decodedVerifyTextBox.Text;
                }
            }
            catch (Exception ex)
            {
                // Show errors
                if (ex.InnerException != null)
                {
                    MessageBox.Show(ex.Message + "\n" + ex.InnerException.Message);
                }
                else
                {
                    MessageBox.Show(ex.Message);
                }
            }
            finally
            {
                // Clean up
                if (dataFile != null) { dataFile.Close(); }
                if (encodedFile != null) { encodedFile.Close(); }
                if (decodedFile != null) { decodedFile.Close(); }
                if (reencodedFile != null) { reencodedFile.Close(); }
                if (cms != null) { cms.Dispose(); }                
            }

        }

        private void verifyButton_Click(object sender, EventArgs e)
        {
            // Variables
            FileStream encodedFile = null;
            FileStream decodedFile = null;
            FileStream dataFile = null;
            SignedLargeCMS cms = null;
            DateTime[] signingTimes = null;
            X509Certificate2Collection signerCerts = null;
            int iCount = 0;

            try
            {
                // Open file with message to decode
                encodedFile = File.Open(encodedVerifyTextBox.Text, FileMode.Open);

                if (detachedVerifyCheckBox.Checked)
                {
                    // Detached message

                    // Open file with original data
                    dataFile = File.Open(dataVerifyTextBox.Text, FileMode.Open);

                    // Decode message
                    cms = new SignedLargeCMS();
                    cms.Decode(dataFile, encodedFile, null);
                }
                else
                {
                    // Original data is attached to encoded file

                    // Create file for decoded data
                    decodedFile = File.Create(decodedVerifyTextBox.Text);

                    // Decode message
                    cms = new SignedLargeCMS();
                    cms.Decode(null, encodedFile, decodedFile);
                    // Note: We can just verify the signature without writing decoded file to disk:
                    //cms.Decode(null, encodedFile, null);
                }

                // Get some info from message that we can use to verify signer certs
                signingTimes = cms.SigningTimes;
                signerCerts = cms.SignerCertificates;
                iCount = 0;
                foreach (X509Certificate2 signerCert in signerCerts)
                {
                    MessageBox.Show("Signing Time = " + signingTimes[iCount].ToString() + "\nSigning Cert Subject = " + signerCert.Subject);
                    iCount++;
                }

                // Verify signature
                cms.CheckSignature();
                MessageBox.Show("Signature verified successfully!!!");
            }
            catch (Exception ex)
            {
                // Show errors
                if (ex.InnerException != null)
                {
                    MessageBox.Show(ex.Message + "\n" + ex.InnerException.Message);
                }
                else
                {
                    MessageBox.Show(ex.Message);
                }
            }
            finally
            {
                // Clean up
                if (encodedFile != null) { encodedFile.Close(); }
                if (decodedFile != null) { decodedFile.Close(); }
                if (dataFile != null) { dataFile.Close(); }
                if (cms != null) { cms.Dispose(); }                
            }

        }

        private void detachedCosignCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            dataCosignLabel.Visible = detachedCosignCheckBox.Checked;
            dataCosignTextBox.Visible = detachedCosignCheckBox.Checked;
            decodedCosignTextBox.Visible = !detachedCosignCheckBox.Checked;
            decodedCosignLabel.Visible = !detachedCosignCheckBox.Checked;
        }

        private void detachedVerifyCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            dataVerifyLabel.Visible = detachedVerifyCheckBox.Checked;
            dataVerifyTextBox.Visible = detachedVerifyCheckBox.Checked;
            decodedVerifyLabel.Visible = !detachedVerifyCheckBox.Checked;
            decodedVerifyTextBox.Visible = !detachedVerifyCheckBox.Checked;
        }

        private void dataSignTextBox_TextChanged(object sender, EventArgs e)
        {
            dataCosignTextBox.Text = dataSignTextBox.Text;
            dataVerifyTextBox.Text = dataSignTextBox.Text;
        }

        private void detachedSignCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            detachedCosignCheckBox.Checked = detachedSignCheckBox.Checked;
        }

        #endregion

        #region "EnvelopedLargeCMS Test"

        private void encodeButton_Click(object sender, EventArgs e)
        {
            // Variables
            X509Store store = null;
            X509Certificate2Collection certs = null;
            FileStream dataFile = null;
            FileStream encodedFile = null;
            EnvelopedLargeCMS cms = null;

            try
            {
                // Get recipient certs
                store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
                store.Open(OpenFlags.MaxAllowed);
                certs = new X509Certificate2Collection();
                certs.Add(store.Certificates.Find(X509FindType.FindBySubjectName, subject1EncodeTextBox.Text, true)[0]);
                certs.Add(store.Certificates.Find(X509FindType.FindBySubjectName, subject2EncodeTextBox.Text, true)[0]);

                // Open file with data to encode
                dataFile = File.Open(dataEncodeTextBox.Text, FileMode.Open);

                // Create file for encoded message
                encodedFile = File.Create(encodedEncodeTextBox.Text);

                // Encode data
                cms = new EnvelopedLargeCMS();
                cms.EncryptAndEncode(certs, Win32.szOID_RSA_DES_EDE3_CBC, dataFile, encodedFile);

                // Success. Inform user
                MessageBox.Show("Encoding done successfully!!!");
            }
            catch (Exception ex)
            {
                // Show errors
                if (ex.InnerException != null)
                {
                    MessageBox.Show(ex.Message + "\n" + ex.InnerException.Message);
                }
                else
                {
                    MessageBox.Show(ex.Message);
                }
            }
            finally
            {
                // Clean up
                if (store != null) { store.Close(); }
                if (dataFile != null) { dataFile.Close(); }
                if (encodedFile != null) { encodedFile.Close(); }
                if (cms != null) { cms.Dispose(); }                
            }
        }

        private void decodeButton_Click(object sender, EventArgs e)
        {
            // Variables
            FileStream encodedFile = null;
            FileStream decodedFile = null;
            EnvelopedLargeCMS cms = null;
            X509Certificate2Collection recipients = null;

            try
            {
                // Open file with data to decode
                encodedFile = File.Open(encodedDecodeTextBox.Text, FileMode.Open);

                // Create file for encoded message
                decodedFile = File.Create(this.decodedDecodeTextBox.Text);

                // Decode data
                cms = new EnvelopedLargeCMS();
                cms.DecodeAndDecrypt(encodedFile, decodedFile);

                // Get all recipients
                recipients = cms.Recipients;
                foreach (X509Certificate2 recipient in recipients)
                {
                    MessageBox.Show("Cert Subject = " + recipient.Subject);
                }

                // Success. Inform user
                MessageBox.Show("Decoding done successfully!!!");
            }
            catch (Exception ex)
            {
                // Show errors
                if (ex.InnerException != null)
                {
                    MessageBox.Show(ex.Message + "\n" + ex.InnerException.Message);
                }
                else
                {
                    MessageBox.Show(ex.Message);
                }
            }
            finally
            {
                // Clean up
                if (encodedFile != null) { encodedFile.Close(); }
                if (decodedFile != null) { decodedFile.Close(); }
                if (cms != null) { cms.Dispose(); }                
            }
        }
        
        #endregion

    }
}
